#include <inputmanager.hpp>
#include <lock_manager/lock_manager.hpp>
#include <elog.h>


#include "efsm.hpp"
#include "efsm_event.hpp"

#include <autoinit.hpp>
#include <boost/thread.hpp>


static boost::mutex mutex; 

normal_state_manmager* normal_state_manmager::p_normal_state_manmager_instance = NULL;

normal_state_manmager :: normal_state_manmager() {
}

normal_state_manmager :: ~normal_state_manmager(){
}


normal_state_manmager* normal_state_manmager::get_normal_state_manmager(){
    boost::unique_lock<boost::mutex> lock(mutex);
    
    if(p_normal_state_manmager_instance == NULL)  {

        p_normal_state_manmager_instance = new normal_state_manmager;
    }
    
    return p_normal_state_manmager_instance;
}


/** 由硬件触发此函数的回调，
 *   此处的职责是处理业务逻辑，包括完成系统状态机切换等事务 **/
void normal_state_manmager :: Update(inputmanager* in_manager){

    this->dev_para = in_manager->getstate();
    log_w("input_type = %d,  input_code = %c \n",    this->dev_para->input_type, this->dev_para->input_code);
    log_w("input_value = %d, execption_id = %d \n",  this->dev_para->input_value, this->dev_para->execption_id);

}


void normal_status_auth_permission(EFSM_EVENT_TYPE event, void *arg){ 
    int* local_arg = reinterpret_cast<int*>(arg);

    log_w("normal_status_auth_permission: %d,  %d\n", event, *local_arg);

    /** 反馈事件发送方 **/
    *local_arg = 8899; 

    return ;
}
 
   

/*
   这里的normal_status_auth_permission是全局函数，后续希望修改为类成员函数
   希望维护一个normal_state_manmager对象，负责普通验证模式，这样才会更贴近面向对象方法学。
   而EFSM采用C编写，使得基于EFSM编写的代码更具有面向过程的特点。
   为了维持本工程CPP代码的面向对象的特性，我希望不采用面向过程的EFSM。
   希望采用boost的信号与槽来自己封装一个管理类，该类的内部会维护各个信号与槽之间的关系

 需要熟悉boost 信号与槽 的使用方法，设计一个类，内有信号发送 和 槽函数。
 ps： 一个信号，支持获取返回值，还可以动态绑定任意槽函数、绑定多个槽函数，支持设置优先级，待实测。

 我可以通过boost的信号与槽来实现类似EFSM的功能，设计一个基类，内含虚的信号、虚的槽函数， 再设计一个子类继承之，也有信号、槽函数等

 但是借助boost库的信号与槽，我想实现上述功能，有点难度。 没撤。( QT的信号与槽，就比较友好。signal, emit 等 )
 */

/* 1. define you own state name      */
EFSM_CREATE(normal_mode_efsmsets);


/* 2. define a sets of event-handler */
static EFSM_SETS normal_mode_efsmsets[] = { 

     /*** 验证权限 ***/ 
    {event_auth_permission,    normal_status_auth_permission},

};
                        

void  normal_mode_init(void) {	
	/* 3. bind your state to sets */
	EFSM_BIND(normal_mode_efsmsets, normal_mode_efsmsets);	
}

auto_dev_init(normal_mode_init);


